
//
// 110520 - AH - (Special) Created.
//

package org.soekrat.engine.wheel;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import org.soekrat.AttributeObject;
import org.soekrat.engine.visitor.SplitScale;
import org.soekrat.engine.visitor.TokenizedLine;
import org.soekrat.engine.wheel.ontology.Ontology;
import org.soekrat.engine.wheel.retrieval.RetrievalEvent;
import org.soekrat.engine.wheel.retrieval.RetrievalEventTree;
import org.soekrat.engine.wheel.retrieval.RetrievalEventType;

/**
 * <p>
 * </p>
 * @author Arne Halvorsen (AH)
 */
public final class Processing 
{
  private final RetrievalEventTree m_tree;
  
  private final int m_turns;
  
  private final Wheel m_wheel;
  
  public Processing(RetrievalEventTree tree, int turns, Wheel wheel)
  {
    if (tree==null)
    {
      throw new NullPointerException("tree");
    }
    
    m_tree=tree;
    m_turns=turns;
    m_wheel=wheel;
  }
  
  /**
   * <p>
   * </p>
   * @param sp
   * @return
   */
  public List<AttributeObject> perform(SplitScale sp)
  {
    if (sp==null)
    {
      throw new NullPointerException("sp");
    }
    
    //System.out.println("perform, number of turns: "+m_turns);
    //System.out.println("input levels");
    //System.out.println(sp);
    //System.out.println("--------------------------------");
    
    RetrievalEvent head=new RetrievalEvent("Start", RetrievalEventType.STEP, 
      null);
    RetrievalEvent tail=head;
    
    List<AttributeObject> paint=new ArrayList<AttributeObject>();
    int n=sp.getLevelCount();
    for (int i=0; i<n && paint.isEmpty(); i++)
    {
      TokenizedLine level=sp.getLevel(i);
      
      //System.out.println();
      //System.out.println("  perform, level: "+level);
      
      performTurns(paint, level, head, tail);
    }
    
    m_tree.addRoot(head);
    
    return paint;
  }
  
  private void performTurns(List<AttributeObject> paint, TokenizedLine input, 
    RetrievalEvent head, RetrievalEvent tail)
  {
    int levelPassCount=0;
    
    int n=(m_turns<1) ? getNumberOfTurns(m_wheel) : m_turns;
    
    for (int i=0; i<n; i++)
    {
      int turnPassCount=performTurn(paint, input, i, head, tail);
      levelPassCount=turnPassCount+levelPassCount;
    }
  }
  
  private int performTurn(List<AttributeObject> paint, TokenizedLine input, 
    int turn, RetrievalEvent head, RetrievalEvent tail)
  {
    int passCount=0;
    
    List<Ontology> spokes=m_wheel.getOntologiesForTurn();
    for (Ontology spoke : spokes)
    {
      if (!paint.isEmpty()) paint.clear();
    
      List<AttributeObject> local=new ArrayList<AttributeObject>();
    
      //System.out.println();
      //System.out.println("      performTurn, ontology: "+spoke.getName());
      //System.out.println("      performTurn, input: "+input);
      
      RetrievalEvent currEvent=spoke.scanAndPaint(input, local);
      AttributeObject.toString(local);
      
      currEvent.setTurn(turn);
      tail.addTail(currEvent);
      tail=currEvent;
      
      if (tail.getType()==RetrievalEventType.PASS) passCount++;

      if (!local.isEmpty())
      {
        //System.out.println("      performTurn retrieved: "+
        //  AttributeObject.toString(local));
        
        input=spoke.getTokens(local);
      
        //System.out.println("      performTurn passes to next ontology input: "+
        //  input);
        
        paint.clear();
        paint.addAll(local);
      }
    }
    
    return passCount;
  }
  
  //
  // Used internally to decide number of turns when not decided by end user,
  // currently is a random number from 1 to (including) the number of spokes.
  //
  private int getNumberOfTurns(Wheel wheel)
  {
    int n=wheel.getNumberOfOntologies();
    Random rnd=new Random();
    return rnd.nextInt(n)+1;
  }
  
}
